#include "VSFreeCameraController.h"
#include "VSCamera.h"
#include "VSQuat.h"
#include "VSGraphicInclude.h"
#include "VSStream.h"
using namespace VSEngine2;
IMPLEMENT_RTTI(VSFreeCameraController,VSController)
static bool gs_bStreamRegistered_VSFreeCameraController = VSFreeCameraController::RegisterMainFactory ();
bool VSFreeCameraController::ms_bRegisterMainFactory = false;
bool VSFreeCameraController::RegisterMainFactory()
{
	if (!ms_bRegisterMainFactory)
	{ 
		VSMain::AddInitialFuntion(VSFreeCameraController::InitialClassFactory); 
		ms_bRegisterMainFactory = true;
	} 
	return ms_bRegisterMainFactory;

}
bool VSFreeCameraController::InitialClassFactory()
{
	ms_ClassFactory.AddElement(ms_Type.GetName(),FactoryFunc);
	
	return 1;
}
VSObject * VSFreeCameraController::FactoryFunc()
{
	return VS_NEW VSFreeCameraController;


}
VSFreeCameraController::VSFreeCameraController()
{
	m_RotXDelta = 1.0;
	m_RotYDelta = 1.0;
	m_RotZDelta = 1.0;
	m_MoveDelta = 1.0;
}
VSFreeCameraController:: ~VSFreeCameraController()
{

}
bool VSFreeCameraController::UpdateEx(double dAppTime)
{
	if(!VSController::UpdateEx(dAppTime))
		return 0;


	//VSFreeCamera * Temp = (VSFreeCamera *)m_pObject;

	VSCamera* Temp = DynamicCast<VSCamera>(m_pObject);
	if(!Temp)
		return 0;
	Temp->m_RotX += m_RotXDelta * (VSREAL)m_dIntervalTime;
	Temp->m_RotY += m_RotYDelta * (VSREAL)m_dIntervalTime;
	Temp->m_RotZ += m_RotZDelta * (VSREAL)m_dIntervalTime;
	
	
	if (Temp->m_RotX > VS2PI) Temp->m_RotX -= VS2PI;
	else if (Temp->m_RotX < -VS2PI) Temp->m_RotX += VS2PI;

	if (Temp->m_RotY > VS2PI) Temp->m_RotY -= VS2PI;
	else if (Temp->m_RotY < -VS2PI) Temp->m_RotY += VS2PI;

	if (Temp->m_RotZ > VS2PI) Temp->m_RotZ -= VS2PI;
	else if (Temp->m_RotZ < -VS2PI) Temp->m_RotZ += VS2PI;
	
	VSVector3 LocalPos = Temp->GetLocalTranslate();
 	LocalPos += m_MoveDirection * m_MoveDelta * (VSREAL)m_dIntervalTime;
			
	VSQuat    qFrame(0,0,0,1);	
	qFrame.CreateEuler(Temp->m_RotX, Temp->m_RotY, Temp->m_RotZ);

	VSMatrix3X3 Mat;
	Mat.Identity();
	qFrame.GetMatrix(Mat);

	Temp->SetLocalRotate(Mat);
	Temp->SetLocalTranslate(LocalPos);
	return 1;
}
unsigned int VSFreeCameraController::DiskUse()const
{
	unsigned int Use = VSController::DiskUse();

	Use += sizeof(VSREAL) * 4;
	Use += sizeof(VSVector3);	
	return Use;

}
bool VSFreeCameraController::Save(VSStream & rStream,unsigned int &iSaveUse)const
{
	if(!VSController::Save(rStream,iSaveUse))
		return 0;


	if(!rStream.Write(&m_RotXDelta,sizeof(VSREAL)))
		return 0;
	iSaveUse +=sizeof(VSREAL);

	if(!rStream.Write(&m_RotYDelta,sizeof(VSREAL)))
		return 0;
	iSaveUse +=sizeof(VSREAL);

	if(!rStream.Write(&m_RotZDelta,sizeof(VSREAL)))
		return 0;
	iSaveUse +=sizeof(VSREAL);

	if(!rStream.Write(&m_MoveDelta,sizeof(VSREAL)))
		return 0;
	iSaveUse +=sizeof(VSREAL);

	if(!rStream.Write(&m_MoveDirection,sizeof(VSVector3)))
		return 0;
	iSaveUse +=sizeof(VSVector3);
	return 1;
}
bool VSFreeCameraController::Load(VSStream & rStream,unsigned int &iSaveUse)
{
	if(!VSController::Load(rStream,iSaveUse))
		return 0;

	if(!rStream.Read(&m_RotXDelta,sizeof(VSREAL)))
		return 0;
	iSaveUse +=sizeof(VSREAL);

	if(!rStream.Read(&m_RotYDelta,sizeof(VSREAL)))
		return 0;
	iSaveUse +=sizeof(VSREAL);

	if(!rStream.Read(&m_RotZDelta,sizeof(VSREAL)))
		return 0;
	iSaveUse +=sizeof(VSREAL);

	if(!rStream.Read(&m_MoveDelta,sizeof(VSREAL)))
		return 0;
	iSaveUse +=sizeof(VSREAL);

	if(!rStream.Read(&m_MoveDirection,sizeof(VSVector3)))
		return 0;
	iSaveUse +=sizeof(VSVector3);
	return 1;
}
bool VSFreeCameraController::Clone(const VSObject *pObject,unsigned int uiType)
{
	const VSFreeCameraController* Temp = DynamicCast<VSFreeCameraController>(pObject); 
	if(!Temp)
		return 0;
	if(VSController::Clone(pObject,uiType))
	{
		
		m_RotXDelta = Temp->m_RotXDelta;
		m_RotYDelta = Temp->m_RotYDelta;
		m_RotZDelta = Temp->m_RotZDelta;
		m_MoveDelta = Temp->m_MoveDelta;
		m_MoveDirection	= Temp->m_MoveDirection;
		return 1;
	}
	else
	{
		return 0;

	}


}